package com.dhcc.bpm.modules.common.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dhcc.bpm.common.constant.FilePathConstant;
import com.dhcc.bpm.common.utils.CreateErrorWordUtils;
import com.dhcc.bpm.common.utils.DateUtils;
import com.dhcc.bpm.modules.common.entity.Plupload;
import com.dhcc.bpm.modules.common.entity.Upload;
import com.dhcc.bpm.modules.common.mapper.PluploadMapper;
import com.dhcc.bpm.modules.common.service.IPluploadService;
import com.dhcc.bpm.modules.common.vo.PluploadVO;
import com.dhcc.bpm.modules.metadata.entity.Metadata;
import com.dhcc.bpm.modules.metadata.mapper.MetadataMapper;
import com.dhcc.bpm.modules.scf.util.OBSUtil;
import com.dhcc.bpm.modules.system.entity.Param;
import com.dhcc.bpm.modules.system.service.ISerialNumberService;
import com.dhcc.bpm.modules.system.service.impl.ParamServiceImpl;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.google.common.collect.Lists;
import fr.opensagres.poi.xwpf.converter.core.FileImageExtractor;
import fr.opensagres.poi.xwpf.converter.core.FileURIResolver;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.w3c.dom.Document;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

/**
 * @ClassName PluploadServiceImpl
 * @Description 公共模块表 服务实现类
 * @Author xiafayu
 * @Date 2020/2/21 14:16
 * @Version V1.0
 * @Copyright: 2020 东华软件 . All rights reserved.
 */
@Service("opc_plupload")
@AllArgsConstructor
@NoArgsConstructor
public class PluploadServiceImpl extends BaseServiceImpl<PluploadMapper, Plupload> implements IPluploadService {
    private static Logger log = LoggerFactory.getLogger(PluploadServiceImpl.class);

    private String fileUploadPath;
    @Autowired
    private OBSUtil obsUtil;

    @Value("${bpm.file-public-path}")
    public void setFileUploadPath(String publicPath) {
        fileUploadPath = publicPath;
    }

    @Value("${bpm.file-server-path}")
    private String fileServerPath;

    @Value("${bpm.img-proxy}")
    private String imgProxy;


    private List<String> photoType = Lists.newArrayList("jpg", "png");
    private List<String> wordType = Lists.newArrayList("doc", "docx");

    @Autowired
    private ISerialNumberService serialNumberService;
    @Autowired
    private ParamServiceImpl ParamService;
    @Autowired
    private FastFileStorageClient storageClient;
    @Autowired
    private PluploadMapper pluploadMapper;
    @Autowired
    private MetadataMapper metadataMapper;

    @Override
    public IPage<PluploadVO> selectPluploadPage(IPage<PluploadVO> page, PluploadVO plupload) {
        return page.setRecords(baseMapper.selectPluploadPage(page, plupload));
    }

    @Override
    public Long fileUpload(Plupload plupload, Upload upload, HttpServletRequest request) {
        // 设置word文件夹名称
        String htmlName = serialNumberService.generateSerialNumberByModelCode("word_html");
        String isFlag = request.getHeader("isFlag");
//        String storageName = "" + System.currentTimeMillis();
        String storageName = DateUtils.getDateTimes() + "-";
        String name = null;
        String paramValue = null;
        if (plupload.getStorageType() != null) {
            //表示文档本地上传
            paramValue = String.valueOf(plupload.getStorageType());
        } else {
            // 获取上传文件类型
            Param param = ParamService.getParamByKey("bpm.fileUploadType");
            log.info(param.toString());
            paramValue = param.getParamValue();
        }
        // 本地上传
        if ("1".equals(paramValue)) {
            File dir = new File(fileUploadPath + FilePathConstant.PLATFORMPATH);
            if (!dir.exists()) {
                dir.mkdir();
            }
            // 上传文件
            try {
                String fullPath = null;
                fullPath = localUpload(upload, dir, storageName, htmlName, isFlag);
                //获取文件名称
                name = fullPath.substring(fullPath.lastIndexOf("/") + 1);
                plupload.setStorageName(storageName + name);
                plupload.setOriginalPath(fullPath.substring(0, fullPath.lastIndexOf("/") + 1) + upload.getName());
                plupload.setFileFullpath(fullPath);
            } catch (Exception e) {
                log.error("文件上传失败！", e);
            }
        }
        // FastDFS文件服务器上传
        if ("0".equals(paramValue)) {
            // 获取请求中文件
            MultipartFile file = upload.getMultipartFile();
            StorePath storePath = null;
            try {
                storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
                        FilenameUtils.getExtension(file.getOriginalFilename()), null);
                name = file.getOriginalFilename();
                plupload.setOriginalPath(storePath.getGroup() + "/" + storePath.getPath());
                String docName = name.substring(0, name.lastIndexOf(".")) + ".html";
                if (name.endsWith(".docx") || name.endsWith(".DOCX")) {
                    storePath = fastdfsDocxToHtml(storePath, docName);
                } else if (name.endsWith(".doc") || name.endsWith(".DOC")) {
                    storePath = fastdfsDocToHtml(storePath, docName);
                }

                plupload.setStorageName(storePath.getPath().substring(storePath.getPath().lastIndexOf("/") + 1));
                plupload.setFileFullpath(storePath.getGroup() + "/" + storePath.getPath());

            } catch (Exception e) {
                log.debug("文件上传失败！", e);
                return null;
            }

        }
        plupload.setFileRealname(name);
        plupload.setStorageType(Long.parseLong(paramValue));
        // 入库
        save(plupload);
        Long id = plupload.getId();
        log.info("ID为{}", id);
        return id;
    }

    @Override
    public Long fileUploadS(Plupload plupload, Upload upload) {
        // 设置word文件夹名称
        String name = null;
        String paramValue = null;
        String htmlName = serialNumberService.generateSerialNumberByModelCode("word_html");
//        String storageName = "" + System.currentTimeMillis();
        String storageName = DateUtils.getDateTimes() + "-";
        if (plupload.getStorageType() != null) {
            //表示文档本地上传
            paramValue = String.valueOf(plupload.getStorageType());
        } else {
            // 获取上传文件类型
            Param param = ParamService.getParamByKey("bpm.fileUploadType");
            log.info(param.toString());
            paramValue = param.getParamValue();
        }
        // 本地上传
        if ("1".equals(paramValue)) {
            File dir = new File(fileUploadPath + FilePathConstant.PLATFORMPATH);
            if (!dir.exists()) {
                dir.mkdir();
            }
            // 上传文件
            try {
                String fullPath = null;
                String reqName = upload.getName();
                fullPath = localUpload(upload, dir, storageName, htmlName, "false");
                //获取文件名称
                name = fullPath.substring(fullPath.lastIndexOf("/") + 1);
                plupload.setStorageName(storageName + name);
                plupload.setOriginalPath(fullPath.substring(0, fullPath.lastIndexOf("/") + 1) + reqName);
                plupload.setFileFullpath(fullPath);
            } catch (Exception e) {
                log.error("文件上传失败！", e);
            }
        }
        // FastDFS文件服务器上传
        if ("0".equals(paramValue)) {
            // FastDFS文件服务器上传
            // 获取请求中文件
            MultipartFile file = upload.getMultipartFile();
            StorePath storePath = null;
            try {
                storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
                        FilenameUtils.getExtension(file.getOriginalFilename()), null);
                name = file.getOriginalFilename();

                plupload.setOriginalPath(storePath.getGroup() + "/" + storePath.getPath());
                plupload.setStorageName(storePath.getPath().substring(storePath.getPath().lastIndexOf("/") + 1));
                plupload.setFileFullpath(storePath.getGroup() + "/" + storePath.getPath());

            } catch (Exception e) {
                log.debug("文件上传失败！", e);
                return null;
            }
        }


        plupload.setFileRealname(name);
        plupload.setStorageType(Long.parseLong(paramValue));
        save(plupload);
        Long id = plupload.getId();
        log.info("ID为{}", id);
        return id;
    }

    @Override
    public Long fileUpload(Plupload plupload, Upload upload, String opcSysId, String productNum, HttpServletRequest request) {
        // 设置word文件夹名称
        String htmlName = serialNumberService.generateSerialNumberByModelCode("word_html");
        String isFlag = request.getHeader("isFlag");
//        String storageName = "" + System.currentTimeMillis();
        String storageName = DateUtils.getDateTimes() + "-";
        String name = null;
        String paramValue = null;
        if (plupload.getStorageType() != null) {
            //表示文档本地上传
            paramValue = String.valueOf(plupload.getStorageType());
        } else {
            // 获取上传文件类型
            Param param = ParamService.getParamByKey("bpm.fileUploadType");
            log.info(param.toString());
            paramValue = param.getParamValue();
        }
        // 本地上传
        if ("1".equals(paramValue)) {
            File dir = new File(fileUploadPath + FilePathConstant.PLATFORMPATH);
            if (!dir.exists()) {
                dir.mkdir();
            }
            // 上传文件
            try {
                htmlName = opcSysId + "/" + productNum;
                String fullPath = null;
                String reqName = upload.getName();
                fullPath = localUpload(upload, dir, storageName, htmlName, isFlag);

                //获取文件名称
                name = fullPath.substring(fullPath.lastIndexOf("/") + 1);
                plupload.setStorageName(storageName + name);
                plupload.setOriginalPath(fullPath.substring(0, fullPath.lastIndexOf("/") + 1) + reqName);
                plupload.setFileFullpath(fullPath);
            } catch (Exception e) {
                log.error("文件上传失败！", e);
            }
        }
        // FastDFS文件服务器上传
        if ("0".equals(paramValue)) {
            // 获取请求中文件
            MultipartFile file = upload.getMultipartFile();
            StorePath storePath = null;
            try {
                storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
                        FilenameUtils.getExtension(file.getOriginalFilename()), null);
                name = file.getOriginalFilename();
                plupload.setOriginalPath(storePath.getGroup() + "/" + storePath.getPath());
                String docName = name.substring(0, name.lastIndexOf(".")) + ".html";
                if (name.endsWith(".docx") || name.endsWith(".DOCX")) {
                    storePath = fastdfsDocxToHtml(storePath, docName);
                } else if (name.endsWith(".doc") || name.endsWith(".DOC")) {
                    storePath = fastdfsDocToHtml(storePath, docName);
                }

                plupload.setStorageName(storePath.getPath().substring(storePath.getPath().lastIndexOf("/") + 1));
                plupload.setFileFullpath(storePath.getGroup() + "/" + storePath.getPath());

            } catch (Exception e) {
                log.debug("文件上传失败！", e);
                return null;
            }

        }
        plupload.setFileRealname(name);
        plupload.setStorageType(Long.parseLong(paramValue));

        save(plupload);
        Long id = plupload.getId();
        log.info("ID为{}", id);
        return id;
    }

    @Override
    public Long fileUpload(Plupload plupload, Upload upload, String opcSysId, String productNum, String apiNum, String apiVersion, HttpServletRequest request) {
        // 设置word文件夹名称
        String htmlName = serialNumberService.generateSerialNumberByModelCode("word_html");
        String isFlag = request.getHeader("isFlag");

//        String storageName = "" + System.currentTimeMillis();
        String storageName = DateUtils.getDateTimes() + "-";
        String name = null;
        String paramValue = null;
        if (plupload.getStorageType() != null) {
            //表示文档本地上传
            paramValue = String.valueOf(plupload.getStorageType());
        } else {
            // 获取上传文件类型
            Param param = ParamService.getParamByKey("bpm.fileUploadType");
            log.info(param.toString());
            paramValue = param.getParamValue();
        }
        // 本地上传
        if ("1".equals(paramValue)) {
            File dir = new File(fileUploadPath + FilePathConstant.PLATFORMPATH);
            if (!dir.exists()) {
                dir.mkdir();
            }
            // 上传文件
            try {
                htmlName = opcSysId + "/" + productNum + "/" + apiNum + "/" + apiVersion;
                String fullPath = null;
                String reqName = upload.getName();
                fullPath = localUpload(upload, dir, storageName, htmlName, isFlag);

                //获取文件名称
                name = fullPath.substring(fullPath.lastIndexOf("/") + 1);
                plupload.setStorageName(storageName + name);
                plupload.setOriginalPath(fullPath.substring(0, fullPath.lastIndexOf("/") + 1) + reqName);

                plupload.setFileFullpath(fullPath);
            } catch (Exception e) {
                log.error("文件上传失败！", e);
            }
        }
        // FastDFS文件服务器上传
        if ("0".equals(paramValue)) {
            // 获取请求中文件
            MultipartFile file = upload.getMultipartFile();
            StorePath storePath = null;
            try {
                storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
                        FilenameUtils.getExtension(file.getOriginalFilename()), null);
                name = file.getOriginalFilename();
                plupload.setOriginalPath(storePath.getGroup() + "/" + storePath.getPath());
                String docName = name.substring(0, name.lastIndexOf(".")) + ".html";
                if (name.endsWith(".docx") || name.endsWith(".DOCX")) {
                    storePath = fastdfsDocxToHtml(storePath, docName);
                } else if (name.endsWith(".doc") || name.endsWith(".DOC")) {
                    storePath = fastdfsDocToHtml(storePath, docName);
                }

                plupload.setStorageName(storePath.getPath().substring(storePath.getPath().lastIndexOf("/") + 1));
                plupload.setFileFullpath(storePath.getGroup() + "/" + storePath.getPath());

            } catch (Exception e) {
                log.debug("文件上传失败！", e);
                return null;
            }

        }
        plupload.setFileRealname(name);
        plupload.setStorageType(Long.parseLong(paramValue));
        // 入库
        save(plupload);
        Long id = plupload.getId();
        log.info("ID为{}", id);
        return id;
    }

    //docx转html
    private StorePath fastdfsDocxToHtml(StorePath storePath, String docName) throws Exception {
        okhttp3.OkHttpClient httpClient = new okhttp3.OkHttpClient();
        Request requestUrl = new Request.Builder().url(fileServerPath + storePath.getGroup() + "/" + storePath.getPath()).build();
        Response response = httpClient.newCall(requestUrl).execute();
        if (response.isSuccessful()) {
            XWPFDocument document = new XWPFDocument(response.body().byteStream());
            File imgFile = new File(fileUploadPath);
            if (!imgFile.exists()) {
                imgFile.mkdir();
            }
            XHTMLOptions options = XHTMLOptions.create().URIResolver(new FileURIResolver(imgFile));
            options.setExtractor(new FileImageExtractor(imgFile));
            options.URIResolver((uri) -> {
                StorePath path = null;
                try {
                    String imgName = uri.substring(uri.lastIndexOf("/") + 1, uri.length());
                    InputStream in = new FileInputStream(fileUploadPath + uri);
                    path = storageClient.uploadFile(in, in.available(), FilenameUtils.getExtension(imgName), null);
                    in.close();
                } catch (FileNotFoundException e) {
                    log.error("图片上传异常：{}", e);
                } catch (IOException e) {
                    log.error("图片上传异常：{}", e);
                }
                return imgProxy + path.getGroup() + "/" + path.getPath();
            });
            OutputStream out = new FileOutputStream(new File(fileUploadPath + docName));
            XHTMLConverter.getInstance().convert(document, out, options);
            InputStream inputStream = new FileInputStream(fileUploadPath + docName);
            int fileLength = inputStream.available();//获取文件大小
            storePath = storageClient.uploadFile(inputStream, fileLength, FilenameUtils.getExtension(docName), null);
            log.info("storePath:{}", storePath.getPath());
            inputStream.close();
            //删除文件
            delete(imgFile);
        }
        return storePath;
    }

    //docx转html
    private StorePath fastdfsDocToHtml(StorePath storePath, String docName) throws Exception {
        okhttp3.OkHttpClient httpClient = new okhttp3.OkHttpClient();
        Request requestUrl = new Request.Builder().url(fileServerPath + storePath.getGroup() + "/" + storePath.getPath()).build();
        Response response = httpClient.newCall(requestUrl).execute();
        if (response.isSuccessful()) {
            File imgFile = new File(fileUploadPath);
            if (!imgFile.exists()) {
                imgFile.mkdir();
            }
            HWPFDocument wordDocument = new HWPFDocument(response.body().byteStream());
            ;
            WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
                    DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
            wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> suggestedName);
            wordToHtmlConverter.setPicturesManager((content, pictureType, name, width, height) -> {
                StorePath path = null;
                try {
                    String imgName = name;
                    InputStream in = new FileInputStream(fileUploadPath + imgName);
                    path = storageClient.uploadFile(in, in.available(), FilenameUtils.getExtension(imgName), null);
                    in.close();
                } catch (FileNotFoundException e) {
                    log.error("图片上传异常：{}", e);
                } catch (IOException e) {
                    log.error("图片上传异常：{}", e);
                }
                return imgProxy + path.getGroup() + "/" + path.getPath();
            });
            wordToHtmlConverter.processDocument(wordDocument);
            Document htmlDocument = wordToHtmlConverter.getDocument();
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            DOMSource domSource = new DOMSource(htmlDocument);
            StreamResult streamResult = new StreamResult(outStream);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.setOutputProperty(OutputKeys.METHOD, "html");
            serializer.transform(domSource, streamResult);
            outStream.close();
            String content = new String(outStream.toByteArray());
            FileUtils.writeStringToFile(new File(fileUploadPath + docName), content, "utf-8");
            InputStream inputStream = new FileInputStream(fileUploadPath + docName);
            int fileLength = inputStream.available();//获取文件大小
            storePath = storageClient.uploadFile(inputStream, fileLength, FilenameUtils.getExtension(docName), null);
            log.info("storePath:{}", storePath.getPath());
            inputStream.close();
            //删除文件
            delete(imgFile);
        }
        return storePath;
    }

    public static void delete(File file) {
        if (!file.exists()) return;
        if (file.isFile() || file.list() == null) {
            file.delete();
            log.info("删除:{}", file.getName());
        } else {
            File[] files = file.listFiles();
            for (File file1 : files) {
                delete(file1);
            }
            file.delete();
            log.info("删除:{}", file.getName());
        }

    }

    @Override
    public HttpServletResponse fileDownloadServer(Long id, HttpServletResponse response) {
        Plupload plupload = pluploadMapper.selectById(id);
        response.setContentType("UTF-8");
        response.setCharacterEncoding("UTF-8");
        try {
            DownloadByteArray callback = new DownloadByteArray();
            String fullPath = plupload.getFileFullpath();
            // 截取字符串获取组名
            String groupName = fullPath.substring(0, fullPath.indexOf("/"));
            // 截取字符串获取文件路径
            String path = fullPath.substring(fullPath.indexOf("/") + 1);
            // 下载文件
            byte[] file = storageClient.downloadFile(groupName, path, callback);
            // 设置响应头
            response.setContentType("application/x-msdownload;");
            String fileName = plupload.getFileRealname().replace("\n", "").replace("\r", "").replace("’", "").replace("”", "").replace(":", "").replace("<", "").replace(">", "");

            response.setHeader("Content-disposition",
                    "attachment; filename=" + new String(fileName.getBytes("GBK"), "ISO8859-1"));
            response.setHeader("Content-Length", String.valueOf(file.length));
            OutputStream output = response.getOutputStream();
            output.write(file);
            output.flush();
            output.close();

        } catch (FileNotFoundException e) {
            log.error("异常信息：{}", e);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            log.error("不支持编码格式", e);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            log.error("IO错误！", e);
        }
        return response;
    }

    @Override
    public HttpServletResponse fileDownload(Long id, HttpServletRequest request, HttpServletResponse response) {
        Plupload plupload = pluploadMapper.selectById(id);
        response.setContentType("UTF-8");
        response.setCharacterEncoding("UTF-8");
        InputStream bis;
        BufferedOutputStream bos = null;
        String downLoadPath;
        long fileLength = 0;
        downLoadPath = plupload.getFileFullpath();
        fileLength = new File(downLoadPath).length();
        try {
            if (1 == plupload.getStorageType()) {
                bis = new BufferedInputStream(new FileInputStream(downLoadPath));
                try {
                    String fileName = plupload.getFileRealname().replace("\n", "").replace("\r", "").replace("’", "").replace("”", "").replace(":", "").replace("<", "").replace(">", "");

                    // 设置响应头
                    response.setContentType("application/x-msdownload;");
                    response.setHeader("Content-disposition",
                            "attachment; filename=" + new String(fileName.getBytes("GBK"), "ISO8859-1"));
                    response.setHeader("Content-Length", String.valueOf(fileLength));
                    bos = new BufferedOutputStream(response.getOutputStream());
                    byte[] buff = new byte[2048];
                    int bytesRead;
                    while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                        bos.write(buff, 0, bytesRead);
                    }
                } catch (IOException e) {
                    log.error("IO错误", e);
                } finally {
                    try {
                        if (bis != null) {
                            bis.close();
                        }
                        if (bos != null) {
                            bos.close();
                        }
                    } catch (IOException e) {
                        log.error("IO错误", e);
                    }
                }
            } else if (0 == plupload.getStorageType()) {

                DownloadByteArray callback = new DownloadByteArray();
                String fullPath = plupload.getFileFullpath();
                // 截取字符串获取组名
                String groupName = fullPath.substring(0, fullPath.indexOf("/"));
                // 截取字符串获取文件路径
                String path = fullPath.substring(fullPath.indexOf("/") + 1);
                // 下载文件
                byte[] file = storageClient.downloadFile(groupName, path, callback);
                // 设置响应头
                response.setContentType("application/x-msdownload;");
                String fileName = plupload.getFileRealname().replace("\n", "").replace("\r", "").replace("’", "").replace("”", "").replace(":", "").replace("<", "").replace(">", "");

                response.setHeader("Content-disposition",
                        "attachment; filename=" + new String(fileName.getBytes("GBK"), "ISO8859-1"));
                response.setHeader("Content-Length", String.valueOf(file.length));
                OutputStream output = response.getOutputStream();
                output.write(file);
                output.flush();
                output.close();

            }

        } catch (FileNotFoundException e) {
            log.error("异常信息：{}", e);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            log.error("不支持编码格式", e);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            log.error("IO错误！", e);
        }
        return response;
    }

    @Override
    public boolean fileDelete(Long id) {
        Plupload plupload = pluploadMapper.selectById(id);
        if (plupload == null) {
            return true;
        }
        pluploadMapper.deleteById(plupload.getId());
        Long type = plupload.getStorageType();
        String fileRealname = plupload.getFileRealname();
        //存储名称
        String storageName = plupload.getStorageName();
        // 本地类型文件删除
        if (1 == type) {
            String fileFullpath = plupload.getFileFullpath();
            String path = fileFullpath.substring(0, fileFullpath.lastIndexOf("/"));
            File file;
            if (fileRealname.endsWith(".jpg") || fileRealname.endsWith(".png")) {
                //删除图片
                file = new File(fileFullpath);
                deleteDoc(file);
            } else if (fileRealname.endsWith(".doc") || fileRealname.endsWith(".docx")) {
                //删除word文件
                file = new File(path);
                deleteDoc(file); //删除文件夹和文件内容
            } else {
                //删除其他类型
                file = new File(fileFullpath);
                deleteDoc(file);
            }
            super.removeById(id);
            return true;
            // FastDFS文件服务器文件删除
        } else if (0 == type) {
            storageClient.deleteFile(plupload.getFileFullpath());
            log.info("文件删除成功！文件路径{}", plupload.getFileFullpath());
            super.removeById(id);
            return true;
        }
        return false;
    }

    /**
     * 删除文件夹及文件夹下所有内容
     *
     * @param file
     * @return
     */
    private Boolean deleteDoc(File file) {
        if (file.exists()) {
            if (file.isFile()) { //判断是否是文件，是文件删除
                file.delete();
            } else {   //如果不是，则是文件夹
                File[] files = file.listFiles(); //获取文件夹下的file对象列表
                if (files.length == 0) {   //判断此文件夹下有没有文件或目录
                    file.delete();       //没有的话，直接删除此路径，有的话，遍历此路径，重复以上动作
                } else {
                    for (File file1 : files) {
                        deleteDoc(file1);
                    }
                    file.delete(); //文件夹下所有文件和目录均被清空，删除本文件夹
                }
            }
            return true;
        } else {
            return false;
        }
    }


    /**
     * @author: 陈泽
     * @date: 2019/12/9 16:01
     * @description: 本地上传方法
     * @param: [upload, pluploadDir, storageName]
     * @return: java.lang.String
     */
    private String localUpload(Upload upload, File pluploadDir, String storageName, String htmlName, String isFlag) {
        int chunks = upload.getChunks();// 用户上传文件被分隔的总块数
        int nowChunk = upload.getChunk();// 当前块，从0开始
        String name = null;
        String nowFile = null;
        String docName = null;
        // 这里Request请求类型的强制转换可能出错，配置文件中向SpringIOC容器引入multipartResolver对象即可。
        MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) upload.getRequest();
        // 调试发现map中只有一个键值对
        MultiValueMap<String, MultipartFile> map = multipartHttpServletRequest.getMultiFileMap();

        if (map != null) {
            try {
                Iterator<String> iterator = map.keySet().iterator();
                String key;
                List<MultipartFile> multipartFileList = null;
                File targetFile;
                File tempFile;
                while (iterator.hasNext()) {
                    key = iterator.next();
                    multipartFileList = (List<MultipartFile>) map.get(key);
                    for (MultipartFile multipartFile : multipartFileList) {    // 循环只进行一次
                        upload.setMultipartFile(multipartFile);// 手动向Plupload对象传入MultipartFile属性值
                        //String fileName = storageName + multipartFile.getOriginalFilename();
                        //获取上传文件名称
                        String fileName = multipartFile.getOriginalFilename();
                        String docFile = storageName + upload.getName();
                        nowFile = docFile.substring(0, docFile.lastIndexOf("."));
                        // 新建目标文件，只有被流写入时才会真正存在
                        targetFile = new File(pluploadDir + "/" + htmlName);
                        if (!targetFile.exists()) {
                            targetFile.mkdirs();
                        }
                        targetFile = new File(pluploadDir + "/" + htmlName, fileName);
                        //文件夹不存在则创建
                        if (!targetFile.exists()) {
                            targetFile.createNewFile();
                        }
//						if(!targetFile.getParentFile().exists()){
//							targetFile.getParentFile().mkdirs();
//						}
                        if (chunks > 1) {// 用户上传资料总块数大于1，要进行合并
                            tempFile = new File(pluploadDir.getPath(), multipartFile.getName());
                            // 第一块直接从头写入，不用从末端写入
                            savePluploadFile(multipartFile.getInputStream(), tempFile, nowChunk == 0 ? false : true);
                            if (chunks - nowChunk == 1) {// 全部块已经上传完毕，此时targetFile因为有被流写入而存在，要改文件名字
                                tempFile.renameTo(targetFile);
                            }
                            name = multipartFile.getOriginalFilename();
                        } else {
                            // 只有一块，就直接拷贝文件内容
                            multipartFile.transferTo(targetFile);
                            name = multipartFile.getOriginalFilename();
                        }
                    }
                }
            } catch (IOException e) {
                log.error("文件上传失败！", e);
            }
        }
        String filePath = null;
        //根据word文件类型转换成html
        filePath = pluploadDir + "/" + htmlName + "/";
        if (name.endsWith(".DOCX") || name.endsWith(".docx")) {
            try {
                docName = docxToHtml(filePath, name, isFlag);
            } catch (Exception e) {
                log.error("word转换HTML异常信息：{}", e);
            }
        } else if (name.endsWith(".DOC") || name.endsWith(".doc")) {
            try {
                docName = docToHtml(filePath, name, isFlag);
            } catch (Exception e) {
                log.error("word转换HTML异常信息：{}", e);
            }
        } else {
            docName = name;
        }
        //返回文件全路径
        String fullPath = filePath + docName;
        fullPath = fullPath.replace("\\", "/").replace(fileUploadPath, FilePathConstant.FILEPROXY);
        return fullPath;
    }

    /**
     * @author: 陈泽
     * @date: 2019/12/9 16:02
     * @description: 将文件保存到本地方法
     * @param: [inputStream, tempFile, flag]
     * @return: void
     */
    private static void savePluploadFile(InputStream inputStream, File tempFile, boolean flag) {
        OutputStream outputStream = null;
        try {
            if (flag == false) {
                // 从头写入
                outputStream = new BufferedOutputStream(new FileOutputStream(tempFile));
            } else {
                // 从末端写入,追加
                outputStream = new BufferedOutputStream(new FileOutputStream(tempFile, true));
            }
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = (inputStream.read(bytes))) > 0) {
                outputStream.write(bytes, 0, len);
            }
        } catch (FileNotFoundException e) {
            log.error("异常信息：{}", e);
        } catch (IOException e) {
            log.error("异常信息：{}", e);
        } finally {
            try {
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                log.error("异常信息：{}", e);
            }
        }
    }

    @Override
    public Upload getFile(Upload upload) {
        MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) upload
                .getRequest();
        // 调试发现map中只有一个键值对
        MultiValueMap<String, MultipartFile> map = multipartHttpServletRequest.getMultiFileMap();
        if (map != null) {
            String key;
            Iterator<String> iterator = map.keySet().iterator();
            List<MultipartFile> multipartFileList;
            while (iterator.hasNext()) {
                key = iterator.next();
                multipartFileList = map.get(key);
                for (MultipartFile multipartFile : multipartFileList) {// 循环只进行一次
                    upload.setMultipartFile(multipartFile);// 手动向Plupload对象传入MultipartFile属性值
                }
            }
        }
        return upload;
    }

    /**
     * 上传头像
     *
     * @param plupload
     * @param upload
     * @param request
     * @return
     */
    @Override
    public String photoUpload(Plupload plupload, Upload upload, HttpServletRequest request) {
        // 设置word文件夹名称
        String wordName = serialNumberService.generateSerialNumberByModelCode("word_html");
//        String storageName = "" + System.currentTimeMillis();
        String storageName = DateUtils.getDateTimes() + "-";
        String name = null;
        String paramValue = null;
        if (plupload.getStorageType() != null) {
            //表示文档本地上传
            paramValue = String.valueOf(plupload.getStorageType());
        } else {
            // 获取上传文件类型
            Param param = ParamService.getParamByKey("bpm.fileUploadType");
            log.info(param.toString());
            paramValue = param.getParamValue();
        }
        // 本地上传
        if ("1".equals(paramValue)) {
            File dir = new File(fileUploadPath);
            if (!dir.exists()) {
                dir.mkdir();
            }
            // 上传文件
            try {
                String fullPath = null;
                fullPath = localFileUpload(upload, dir, storageName, wordName);

                name = upload.getName();
                plupload.setStorageName(storageName + name);
                plupload.setFileFullpath(fullPath);
                plupload.setOriginalPath(fullPath);

            } catch (Exception e) {
                log.error("文件上传失败！", e);
            }
        }
        // // FastDFS文件服务器上传
        // if ("0".equals(paramValue)) {
        //     // 获取请求中文件
        //     //Upload uploadEntity = getFile(upload);
        //     MultipartFile file = upload.getMultipartFile();
        //     StorePath storePath = null;
        //     try {
        //         storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
        //                 FilenameUtils.getExtension(file.getOriginalFilename()), null);
        //         name = file.getOriginalFilename();
        //         plupload.setStorageName(storePath.getPath().substring(storePath.getPath().lastIndexOf("/") + 1));
        //         plupload.setFileFullpath(storePath.getGroup() + "/" + storePath.getPath());
        //         plupload.setOriginalPath(storePath.getGroup() + "/" + storePath.getPath());
        //     } catch (Exception e) {
        //         log.error("文件上传失败！", e);
        //     }
        //
        // }
        // OBS文件服务器上传
        if ("0".equals(paramValue)) {
            // 获取请求中文件
            MultipartFile file = upload.getMultipartFile();
            HashMap<String, String> stringStringHashMap;
            try {
                // 1.获取上传的文件原始名称
                String fileName = StringUtils.cleanPath(file.getOriginalFilename());
                // 生成随机数作为文件名的前缀
                String randomPrefix = UUID.randomUUID().toString().replaceAll("-", "");

                // 获取原始文件名的后缀
                String fileExtension = StringUtils.getFilenameExtension(fileName);
                // 构建新的文件名
                String newFileName = randomPrefix + "." + fileExtension;
                stringStringHashMap = obsUtil.uploadFile(file, "TX/" + newFileName);
                name = file.getOriginalFilename();
                // 正式objectKey
                String objectKey = "TXFile" + "/" + newFileName;
                obsUtil.copyFile(objectKey, stringStringHashMap.get("objectKey"));
                plupload.setStorageName(fileName);
                plupload.setFileFullpath(objectKey);
                plupload.setOriginalPath(objectKey);
            } catch (Exception e) {
                log.error("文件上传失败！", e);
            }

        }
        plupload.setFileRealname(name);
        plupload.setStorageType(Long.parseLong(paramValue));

        // 入库
        save(plupload);
        String fileFullpath = plupload.getFileFullpath();
        log.info("path为{}", fileFullpath);
        String fileFullpathObs = obsUtil.getDownloadUrl(fileFullpath);
        return fileFullpathObs;
    }

    //docx转html
    private String docxToHtml(String filePath, String name, String isFlag) throws Exception {
        String docName = name.substring(0, name.lastIndexOf(".")) + ".html";
        InputStream in = null;
        OutputStream dest = null;
        try {
            in = new FileInputStream(filePath + name);
            XWPFDocument document = new XWPFDocument(in);
            if (isFlag.equals("true")) {
                List<Metadata> list = metadataMapper.selectMetadataListByCode();
                if (list != null) {
                    XWPFDocument xdoc = new XWPFDocument();
                    CreateErrorWordUtils.createTable(xdoc, list);
                    CreateErrorWordUtils.appendBody(document, xdoc);
                    dest = new FileOutputStream(filePath + name);
                    document.write(dest);
                    document = new XWPFDocument(new FileInputStream(filePath + name));
                }
            }
            File imgFile = new File(filePath);
            XHTMLOptions options = XHTMLOptions.create().URIResolver(new FileURIResolver(imgFile));
            options.setExtractor(new FileImageExtractor(imgFile));
            OutputStream out = new FileOutputStream(new File(filePath + docName));
            XHTMLConverter.getInstance().convert(document, out, options);
        } catch (Exception e) {
            log.error("docx转HTML异常：{}", e);
        } finally {
            if (dest != null) {
                dest.close();
            }
            if (in != null) {
                in.close();
            }
        }
        return docName;
    }


    //doc转html
    private static String doc2Html(String filePath, String name) throws Exception {
        String docName = name.substring(0, name.lastIndexOf(".")) + ".html";
        InputStream in = new FileInputStream(filePath + name);
        HWPFDocument wordDocument = new HWPFDocument(in);
        WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
        //解析word文档
        wordToHtmlConverter.processDocument(wordDocument);
        Document htmlDocument = wordToHtmlConverter.getDocument();
        File htmlFile = new File(filePath + docName);
        OutputStream outStream = new FileOutputStream(htmlFile);
        DOMSource domSource = new DOMSource(htmlDocument);
        StreamResult streamResult = new StreamResult(outStream);
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer serializer = factory.newTransformer();
        serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
        serializer.setOutputProperty(OutputKeys.INDENT, "yes");
        serializer.setOutputProperty(OutputKeys.METHOD, "html");
        serializer.transform(domSource, streamResult);
        outStream.close();
        return docName;
    }

    //doc转html
    private String docToHtml(String filePath, String name, String isFlag) throws Exception {
        String docName = name.substring(0, name.lastIndexOf(".")) + ".html";
//        if (isFlag.equals("true")) {
//            InputStream in = null;
//            HWPFDocument wordDocument = null;
//            try {
//                String docxName = name.substring(0, name.lastIndexOf(".")) + ".docx";
//                File file = new File(filePath + docxName);
//                if (!file.exists()) {
//                    file.createNewFile();
//                }
//                com.spire.doc.Document document = new com.spire.doc.Document(filePath + name);
//                List<Metadata> list = metadataMapper.selectMetadataListByCode();
//                if (list != null) {
//                    XWPFDocument xdoc = new XWPFDocument();
//                    CreateErrorWordUtils.createTable(xdoc, list);
//                    CreateErrorWordUtils.saveDocument(xdoc, filePath + docxName);
//                }
//                document.insertTextFromFile(filePath + docxName, FileFormat.Docx_2013);
//
//                //保存文档
//                document.saveToFile(filePath + name, FileFormat.Docx_2013);
//                docxToHtml(filePath, name, "false");
//            } catch (Exception e) {
//                log.error("doc转HTML异常：{}", e);
//            } finally {
//                if (in != null) {
//                    in.close();
//                }
//            }
//        } else {
//            docToHtml_old(filePath, name, isFlag);
//        }

        docToHtml_old(filePath, name, isFlag);

        return docName;
    }

    //doc转html
    private static String docToHtml_old(String filePath, String name, String isFlag) throws Exception {
        InputStream input = new FileInputStream(filePath + name);
        HWPFDocument wordDocument = new HWPFDocument(input);
        ;
        WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
                DocumentBuilderFactory.newInstance().newDocumentBuilder()
                        .newDocument());
        wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> suggestedName);
        wordToHtmlConverter.processDocument(wordDocument);
        List pics = wordDocument.getPicturesTable().getAllPictures();
        if (pics != null) {
            for (int i = 0; i < pics.size(); i++) {
                Picture pic = (Picture) pics.get(i);
                try {
                    pic.writeImageContent(new FileOutputStream(filePath
                            + pic.suggestFullFileName()));
                } catch (FileNotFoundException e) {
                    log.error("异常信息：{}", e);
                }
            }
        }
        Document htmlDocument = wordToHtmlConverter.getDocument();
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        DOMSource domSource = new DOMSource(htmlDocument);
        StreamResult streamResult = new StreamResult(outStream);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer serializer = tf.newTransformer();
        serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
        serializer.setOutputProperty(OutputKeys.INDENT, "yes");
        serializer.setOutputProperty(OutputKeys.METHOD, "html");
        serializer.transform(domSource, streamResult);
        outStream.close();
        String content = new String(outStream.toByteArray());
        String docName = name.substring(0, name.lastIndexOf(".")) + ".html";
        FileUtils.writeStringToFile(new File(filePath, docName), content, "utf-8");
        return docName;
    }

    /**
     * @param plupload
     * @param upload
     * @param request
     * @return java.lang.Long
     * @Description 本地上传文件
     * @Author sjm
     * @Date 11:19 2020/3/7 0007
     **/
    @Override
    public Long fileLocalUpload(Plupload plupload, Upload upload, HttpServletRequest request) {
        // 设置word文件夹名称
        String wordName = serialNumberService.generateSerialNumberByModelCode("word_html");
//        String storageName = "" + System.currentTimeMillis();
        String storageName = DateUtils.getDateTimes() + "-";
        if (!"".equals(upload.getApiName()) && null != upload.getApiName()) {
            storageName = upload.getApiName() + "-" + storageName;
        }
        String name = null;
        File dir = new File(fileUploadPath);
        if (!dir.exists()) {
            dir.mkdir();
        }
        // 上传文件
        try {
            String fullPath = null;
            fullPath = localFileUpload(upload, dir, storageName, wordName);

            name = upload.getName();
            plupload.setStorageName(storageName + name);
            plupload.setFileFullpath(fullPath);
            plupload.setOriginalPath(fullPath);
        } catch (Exception e) {
            log.error("文件上传失败！", e);
        }
        plupload.setFileRealname(name);
        plupload.setStorageType(1L);
        // 入库
        save(plupload);
        Long id = plupload.getId();
        log.info("ID为{}", id);
        return id;
    }

    /**
     * @param upload
     * @param pluploadDir
     * @param storageName
     * @param wordName
     * @return java.lang.String
     * @Description 本地上传通用方法
     * @Author sjm
     * @Date 11:27 2020/3/7 0007
     **/
    private String localFileUpload(Upload upload, File pluploadDir, String storageName, String wordName) {
        int chunks = upload.getChunks();// 用户上传文件被分隔的总块数
        int nowChunk = upload.getChunk();// 当前块，从0开始
        String name = null;
        String nowFile = null;
        String docName = null;
        String docFile = null;
        String fileName = null;
        // 这里Request请求类型的强制转换可能出错，配置文件中向SpringIOC容器引入multipartResolver对象即可。
        MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) upload.getRequest();
        // 调试发现map中只有一个键值对
        MultiValueMap<String, MultipartFile> map = multipartHttpServletRequest.getMultiFileMap();

        if (map != null) {
            try {
                Iterator<String> iterator = map.keySet().iterator();
                String key;
                List<MultipartFile> multipartFileList = null;
                File targetFile;
                File tempFile;
                while (iterator.hasNext()) {
                    key = iterator.next();
                    multipartFileList = (List<MultipartFile>) map.get(key);
                    for (MultipartFile multipartFile : multipartFileList) {// 循环只进行一次
                        upload.setMultipartFile(multipartFile);// 手动向Plupload对象传入MultipartFile属性值
                        //String fileName = storageName + multipartFile.getOriginalFilename();
                        //获取上传文件名称
                        fileName = multipartFile.getOriginalFilename();
                        docFile = storageName + upload.getName();
                        nowFile = docFile.substring(0, docFile.lastIndexOf("."));
                        //初始化文件夹
                        targetFile = null;
                        //判断是否是图片
                        if (fileName.endsWith(".jpg") || fileName.endsWith(".png")) {
                            targetFile = new File(pluploadDir + "/imgs", docFile);
                            File file = new File(pluploadDir + "/imgs");
                            if (!file.exists()) {
                                file.mkdirs();
                            }
                        } else if (fileName.endsWith(".doc") || fileName.endsWith(".docx")) {
                            // 新建目标文件，只有被流写入时才会真正存在
                            targetFile = new File(pluploadDir + "/" + wordName, docFile);
                            File file = new File(pluploadDir + "/" + wordName);
                            if (!file.exists()) {
                                file.mkdirs();
                            }
                        } else if (fileName.endsWith(".xlsx")) {
                            targetFile = new File(pluploadDir, upload.getName());
                        } else {
                            targetFile = new File(pluploadDir, docFile);
                        }
                        //文件夹不存在则创建
                        if (!pluploadDir.exists()) {
                            pluploadDir.mkdirs();
                        }
                        if (chunks > 1) {// 用户上传资料总块数大于1，要进行合并
                            tempFile = new File(pluploadDir.getPath(), multipartFile.getName());
                            // 第一块直接从头写入，不用从末端写入
                            savePluploadFile(multipartFile.getInputStream(), tempFile, nowChunk == 0 ? false : true);
                            if (chunks - nowChunk == 1) {// 全部块已经上传完毕，此时targetFile因为有被流写入而存在，要改文件名字
                                tempFile.renameTo(targetFile);
                            }
                            name = multipartFile.getOriginalFilename();
                        } else {
                            // 只有一块，就直接拷贝文件内容
                            multipartFile.transferTo(targetFile);
                            name = multipartFile.getOriginalFilename();
                        }
                    }
                }
            } catch (IOException e) {
                log.error("文件上传失败！", e);
            }
        }
        //返回文件全路径
        String fullPath = null;
        //如果存储图片
        String offName = upload.getName();
        if (name.endsWith(".jpg") || name.endsWith(".png")) {
            fullPath = pluploadDir + "/imgs" + "/" + docFile;
        } else if (name.endsWith(".doc") || name.endsWith(".docx")) {
            fullPath = pluploadDir + "/" + wordName + "/" + docFile;
        } else {
            fullPath = pluploadDir + "/" + docFile;
        }
        fullPath = fullPath.replace("\\", "/").replace(fileUploadPath,FilePathConstant.FILEPROXY);
        return fullPath;

    }

    @Override
    public String htmlToWord(String content, String docName) {
        InputStream is = null;
        OutputStream os = null;
        File dir = new File(fileUploadPath);
        if (!dir.exists()) {
            dir.mkdir();
        }
        String wordName = dir + "/" + docName.substring(0, docName.lastIndexOf(".")) + ".docx";
        try {
            is = new ByteArrayInputStream(content.getBytes("UTF-8"));
            os = new FileOutputStream(wordName);
            POIFSFileSystem fs = new POIFSFileSystem();
            fs.createDocument(is, "WordDocument");
            fs.writeFilesystem(os);
        } catch (FileNotFoundException e) {
            log.error("htmlToWord异常：{}", e);
        } catch (IOException e) {
            log.error("htmlToWord异常：{}", e);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error("htmlToWord关闭流异常：{}", e);
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    log.error("htmlToWord关闭流异常：{}", e);
                }
            }
        }

        return wordName;
    }

    @Override
    public Plupload selectById(Long id) {
        return baseMapper.selectById(id);
    }

    @Override
    public Plupload selectByUrl(String url) {
        return baseMapper.selectByUrl(url);
    }
}
